package com.deuwise.job.config;


import com.deuwise.job.entity.ScheduleJob;
import com.deuwise.job.entity.TaskDo;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 *
 *
 * @author chenwenchao
 * @date 2018/5/07 Description:
 * 定时任务类 增删改 可参考api：http://www.quartz-scheduler.org/api/2.2.1/
 *
 * 任务名称 默认为 SysJob 类 id
 */
@Service
public class JobTask {

  private static final Logger log = LoggerFactory.getLogger(JobTask.class);
  @Autowired
  private Scheduler scheduler;

  @Autowired
  SchedulerFactoryBean schedulerFactoryBean;

  /**
   * true 存在 false 不存在
   * @param
   * @return
   */
  public boolean checkJob(TaskDo job){
    Scheduler scheduler = schedulerFactoryBean.getScheduler();
    TriggerKey triggerKey = TriggerKey.triggerKey(job.getId(), Scheduler.DEFAULT_GROUP);
    try {
      if(scheduler.checkExists(triggerKey)){
        return true;
      }
    } catch (SchedulerException e) {
      e.printStackTrace();
    }
    return false;
  }

  /**
   * 开启
   */
  public boolean startJob(TaskDo job) {
    Scheduler scheduler = schedulerFactoryBean.getScheduler();
    try {
      Class clazz = Class.forName(job.getMethodName());
      JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity(job.getId(), Scheduler.DEFAULT_GROUP).build();
      jobDetail.getKey();
      // 触发器
      TriggerKey triggerKey = TriggerKey.triggerKey(job.getId(), Scheduler.DEFAULT_GROUP);
      CronTrigger trigger = TriggerBuilder.newTrigger()
          .withIdentity(triggerKey)
          .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpression())).build();
      scheduler.scheduleJob(jobDetail, trigger);
      // 启动
      if (!scheduler.isShutdown()) {
        scheduler.start();
        log.info("---任务[" + triggerKey.getName() + "]启动成功-------");
        return true;
      }else{
        log.info("---任务[" + triggerKey.getName() + "]已经运行，请勿再次启动-------");
      }
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    return false;
  }

  /**
   * 立即执行job
   *
   * @param scheduleJob
   * @throws SchedulerException
   */
  public void runAJobNow(TaskDo scheduleJob) throws SchedulerException {
    Scheduler scheduler = schedulerFactoryBean.getScheduler();
    TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getId(), Scheduler.DEFAULT_GROUP);
    JobKey jobKey = JobKey.jobKey(scheduleJob.getId(), Scheduler.DEFAULT_GROUP);
    scheduler.triggerJob(jobKey);
  }

  /**
   * 更新
   */
  public boolean updateJob(TaskDo job) {
    Scheduler scheduler = schedulerFactoryBean.getScheduler();
    String createTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");

    TriggerKey triggerKey = TriggerKey.triggerKey(job.getId(), Scheduler.DEFAULT_GROUP);
    try {
      if (scheduler.checkExists(triggerKey)) {
        return false;
      }

      JobKey jobKey = JobKey.jobKey(job.getId(), Scheduler.DEFAULT_GROUP);

      CronScheduleBuilder schedBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression())
          .withMisfireHandlingInstructionDoNothing();
      CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey)
          .withDescription(createTime).withSchedule(schedBuilder).build();
      Class clazz = null;
      JobDetail jobDetail = scheduler.getJobDetail(jobKey);
      HashSet<Trigger> triggerSet = new HashSet<>();
      triggerSet.add(trigger);
      scheduler.scheduleJob(jobDetail, triggerSet, true);
      log.info("---任务["+triggerKey.getName()+"]更新成功-------");
      return true;
    } catch (SchedulerException e) {
      e.printStackTrace();
    }
    return false;
  }

  /**
   * 删除
   */
  public boolean remove(TaskDo job) {
    Scheduler scheduler = schedulerFactoryBean.getScheduler();
    TriggerKey triggerKey = TriggerKey.triggerKey(job.getId(), Scheduler.DEFAULT_GROUP);
    try {
      if (checkJob(job)) {
        scheduler.pauseTrigger(triggerKey);
        scheduler.unscheduleJob(triggerKey);
        scheduler.deleteJob(JobKey.jobKey(job.getId(), Scheduler.DEFAULT_GROUP));
        log.info("---任务[" + triggerKey.getName() + "]删除成功-------");
        return true;
      }
    } catch (SchedulerException e) {
      e.printStackTrace();
    }
    return false;
  }

  /**
   * 获取所有计划中的任务列表
   *
   * @return
   * @throws SchedulerException
   */
  public List<ScheduleJob> getAllJob() throws SchedulerException {
    GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
    Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
    List<ScheduleJob> jobList = new ArrayList<ScheduleJob>();
    for (JobKey jobKey : jobKeys) {
      List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
      for (Trigger trigger : triggers) {
        ScheduleJob job = new ScheduleJob();
        job.setJobName(jobKey.getName());
        job.setJobGroup(jobKey.getGroup());
        job.setDescription("触发器:" + trigger.getKey());
        Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
        job.setJobStatus(triggerState.name());
        if (trigger instanceof CronTrigger) {
          CronTrigger cronTrigger = (CronTrigger) trigger;
          String cronExpression = cronTrigger.getCronExpression();
          job.setCronExpression(cronExpression);
        }
        jobList.add(job);
      }
    }
    return jobList;
  }

  /**
   * 所有正在运行的job
   *
   * @return
   * @throws SchedulerException
   */
  public List<ScheduleJob> getRunningJob() throws SchedulerException {
    List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
    List<ScheduleJob> jobList = new ArrayList<ScheduleJob>(executingJobs.size());
    for (JobExecutionContext executingJob : executingJobs) {
      ScheduleJob job = new ScheduleJob();
      JobDetail jobDetail = executingJob.getJobDetail();
      JobKey jobKey = jobDetail.getKey();
      Trigger trigger = executingJob.getTrigger();
      job.setJobName(jobKey.getName());
      job.setJobGroup(jobKey.getGroup());
      job.setDescription("触发器:" + trigger.getKey());
      Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
      job.setJobStatus(triggerState.name());
      if (trigger instanceof CronTrigger) {
        CronTrigger cronTrigger = (CronTrigger) trigger;
        String cronExpression = cronTrigger.getCronExpression();
        job.setCronExpression(cronExpression);
      }
      jobList.add(job);
    }
    return jobList;
  }

  /**
   * 暂停一个job
   *
   * @param scheduleJob
   * @throws SchedulerException
   */
  public void pauseJob(ScheduleJob scheduleJob) throws SchedulerException {
    JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
    scheduler.pauseJob(jobKey);
  }

  /**
   * 恢复一个job
   *
   * @param scheduleJob
   * @throws SchedulerException
   */
  public void resumeJob(ScheduleJob scheduleJob) throws SchedulerException {
    JobKey jobKey = JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup());
    scheduler.resumeJob(jobKey);
  }

}
